package org.phantom.securityframework.datapermission.internal;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.ibatis.io.Resources;
import org.phantom.securityframework.api.exception.AnnotationConfigureException;
import org.phantom.securityframework.datapermission.DataFilter;
import org.phantom.securityframework.datapermission.DimensionQuery;
import org.phantom.securityframework.datapermission.SqlBuilder;
import org.springframework.stereotype.Service;


/**
 * 简单过滤,当只过滤单表时可以使用
 * 
 * @see com.cmetex.datapermission.internal.MyBatisDao
 * @author apple
 *
 */
@Service("simpleSqlDataProvider")
public class SimpleSqlDataProvider extends AbstractDataProvider{

	
	@Resource(name="sqlBuildOracleImpl")
	private SqlBuilder sqlBuilder;
	
	@Resource
	private MyBatisDao dao = null;
	
	@SuppressWarnings("unchecked")
	@Override
	public Object provide(Object[] args,Annotation anno) throws AnnotationConfigureException {
		if(this.check(anno)){
			DimensionQuery query = this.createDimensionQuery(args,anno);
			String sql = sqlBuilder.build(anno, query);
			try {
				return this.resultHandle((List<Map<String, Object>>) dao.selectList(sql),Resources.classForName(((DataFilter)anno).resultType()));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public int total(Object[] args,Annotation anno) throws AnnotationConfigureException {
		if(this.check(anno)){
			DimensionQuery query = this.createDimensionQuery(args,anno);
			String sql = sqlBuilder.buildCount(anno, query);
			try {
				Map map = (Map) dao.selectOne(sql);
				int total = 0;
				Object t =  map.values().iterator().next();
				if(t instanceof BigDecimal)
					total = new Integer(((java.math.BigDecimal)t).intValue());
				else
					total = (Integer) t;
				return total;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return 0;
	}

	@Override
	public boolean check(Annotation anno) throws AnnotationConfigureException {
		DataFilter filter = (DataFilter) anno;
		if(null == filter.table() || "".equals(filter.table())){
			throw new AnnotationConfigureException("table is require");
		}
		if(null == filter.resultType() || "".equals(filter.resultType())){
			throw new AnnotationConfigureException("resultType is require");
		}
		return true;
	}

	@SuppressWarnings({ "rawtypes", "unchecked"})
	protected Object resultHandle(List<Map<String, Object>> list,Class<?> resultType) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException{
		List result = new ArrayList();
		Constructor constructor = resultType.getDeclaredConstructor();
        if (!constructor.isAccessible()) {
          constructor.setAccessible(true);
        }
        for (Map<String, Object> map : list) {
        	Object o = constructor.newInstance();
			for (String k : map.keySet()) {
				for(Field f : resultType.getDeclaredFields()){
					if(f.getName().toUpperCase().equals(k.toUpperCase())){
						boolean accessable = f.isAccessible();
						f.setAccessible(true);
						if(f.getType().getName().equals(Integer.class.getName())){
							if(map.get(k) instanceof BigDecimal){
								f.set(o, new Integer(((java.math.BigDecimal)map.get(k)).intValue()));
							}else{
								f.set(o, map.get(k));
							}
						}else{
							f.set(o, map.get(k));
						}
						f.setAccessible(accessable);
					}
				}
			}
			result.add(o);
		}
        return result;
	}

}
